/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tencent.tendon.convert.json;

import java.util.Collections;
import java.util.List;

/**
 * 解析时给对象字段赋值的操作接口， 一个字段一个JsonDeHandle
 *
 * @author nbzhang
 */
public final class JsonDeHandle<T, V> extends JsonHandle<T, V> {

	public static final JsonDeHandle<Object, Object> NULL = new JsonDeHandle(null, null);

	public static final JsonDeHandle<Object, Object> REFER = new JsonDeHandle(null, null);

	protected JsonDeHandle<T, ?> parent;

	protected JsonDeHandle<T, ?> next;

	protected JsonDecodable<V> decoder;

	private JsonDeHandle(final JsonAttribute<T, V> attribute, JsonDecodable<V> decoder) {
		super(attribute);
		this.next = null;
		this.parent = null;
		this.decoder = decoder;
	}

	public static <T, V> JsonDeHandle<T, V> create(final JsonAttribute attribute, final JsonDecodable decoder) {
		return new JsonDeHandle(attribute, decoder);
	}

	public final void set(JsonReader in, T obj) {
		this.attribute.set(obj, decoder.convertFrom(in));
	}

	public final V getValue(JsonReader in) {
		return decoder.convertFrom(in);
	}

	public final void setValue(T obj, V value) {
		this.attribute.set(obj, value);
	}

	@Override
	public final boolean isSimpled() {
		return decoder.isSimpled();
	}

	static JsonDeHandle link(final List<JsonDeHandle> handles) {
		if (handles.isEmpty()) return JsonDeHandle.NULL;
		Collections.sort(handles);
		JsonDeHandle head = null;
		int index = 0;
		for (JsonDeHandle handle : handles) {
			if (head != null) {
				head.next = handle;
				handle.parent = head;
			}
			handle.index(index++);
			head = handle;
		}
		return handles.get(0);
	}

	JsonDeHandle find(final String name) {
		char[] names = name.toCharArray();
		return find(names, 0, names.length);
	}

	/**
	 *
	 * @param name
	 * @return
	 */
	public JsonDeHandle find(final char[] names, int start, int len) {
		JsonDeHandle handle = this;
		final int size = len;
		do {
			final char[] localfields = handle.fields;
			if (localfields.length != size) continue;
			boolean flag = true;
			for (int i = 0; i < size; i++) {
				if (names[i + start] != localfields[i]) {
					flag = false;
					break;
				}
			}
			if (flag) return handle;
		} while ((handle = handle.next) != null);
		handle = this;
		while ((handle = handle.parent) != null) {
			final char[] localfields = handle.fields;
			if (localfields.length != size) continue;
			boolean flag = true;
			for (int i = 0; i < size; i++) {
				if (names[i + start] != localfields[i]) {
					flag = false;
					break;
				}
			}
			if (flag) return handle;
		}
		return null;
	}

	@Override
	public final JsonDeHandle<T, ?> next() {
		return this.next;
	}

	public final JsonDeHandle<T, ?> parent() {
		return this.parent;
	}

	public final JsonDeHandle<T, ?> head() {
		JsonDeHandle<T, ?> handle = this;
		while (handle.parent != null) {
			handle = handle.parent;
		}
		return handle;
	}

	@Override
	public String toString() {
		return "{field:" + String.format("%12s", this.field) + ", decoder:" + String.format("%25s", (decoder.isSimpled() ? decoder.toString() : decoder.getClass().getSimpleName())) + ", \r\n   next:" + this.next + "}";
	}
}
